Vue3基础知识
练习demo可以使用sfc: https://sfc.vuejs.org/
01 vite脚手架创建vue3.0项目
(1) 创建vue3项目
npm install -g create-vite-app
create-vite-app projectName
cd projectName
npm install
npm run dev
vit的特点就是: 快sass支持
- 安装sass(不要安装node-sass)
npm i sass sass-loader -D
安装node-sass失败推荐使用dart-sass
- 代码: 要写scss而不是sass
<style lang="scss" scoped>
div {
p {
color: red;
}
}
</style>
(2) 创建vue3+ts项目
执行命令
npm init vite@latest
npm init @vitejs/app vue3_ts_vite
根据提示输入项目名称,选择vue+ts
安装依赖
运行项目
02 setup入口函数
- 使用setup函数和更好的管理我们的代码
- vue2.x的data、methods、computed、watch通通写进了setup函数里面
- 一个简单例子
<template>
<div>{{activeIndex}}</div>
</template>
<script>
import { getUsers } from "../api/repo";
import UserRepoList from "./userRepoList.vue";
import {onMounted, ref} from 'vue';
export default {
components: {
UserRepoList,
},
setup() {
// 把data的东西移到这里
const activeIndex = ref('');
const userId = ref('');
const userList = ref([]);
// 把methods移到这里
const getUserList=()=>{
userList.value = getUsers();
}
const changeUser = (id,index)=>{
activeIndex.value = index;
userId.value = id;
}
// onMounted是介于beforeCreated和created的生命周期, 没有this
onMounted(getUserList);
// 相当于2.x data(){}里的return,其他地方
return {
activeIndex,
userId,
userList,
changeUser
};
}
};
</script>
03 ref 创建响应式数据(2.x的data)
<template>
<div style="margin: 30px">
<p>
{{count}}
</p>
<ol>
<li v-for="(item,index) in list" :key="index">{{item}}</li>
</ol>
</div>
</template>
<script>
import {ref} from 'vue';
export default {
setup(props) {
const count = ref(0);
const list = ref(['a','b','c']);
return {
count,
list
};
},
};
</script>
reactive用法与ref的用法相似,也是将数据变成响应式数据,当数据发生变化时UI也会自动更新。不同的是ref用于基本数据类型,而reactive是用于复杂数据类型,比如对象和数组 例如:定义一个对象类型的变量user
<template>
<div>
<p>{{ user }}</p>
<button @click="increase">click me! one year later</button>
</div>
</template>
<script>
import { reactive } from "vue";
export default {
name: "reactive",
setup() {
const user = reactive({ name: "Alice", age: 12 });
function increase() {
++user.age
}
return { user, increase };
},
};
</script>
04 定义方法和修改响应式数据
- 响应式数据通过count.value = xxx 进行重新赋值
- 方法定义在setup函数里, 并放在return对象里
<template>
<div>
<h3>{{msg}}</h3>
<button @click="changeMsg">修改msg</button>
<h3>{{count}}</h3>
<button @click="changeCount">修改count</button>
<h3>列表 <button @click="changeList">修改list</button></h3>
<ul class="flex">
<li class="ml-5" v-for="(item,index) in list" :key="index">{{item}}</li>
</ul>
</div>
</template>
<script>
import { defineComponent, ref } from 'vue';
export default defineComponent({
name: "App",
setup(props) {
let msg = ref('hello');
// 定义修改msg的方法
const changeMsg = ()=> {
msg.value = 'hello vue3';
}
// 定义修改count的方法
let count = ref(0);
const changeCount =()=> {
count.value++;
}
// 定义修改list的方法
let list = ref(['a','b','c','d']);
const changeList = ()=> {
list.value = [
...list.value,
'新成员',
'新成员',
]
}
return {
msg,
changeMsg,
count,
changeCount,
list,
changeList
};
},
});
</script>
05 toRefs 把props变成响应式数据
<template>
<div style="margin: 30px">
{{ count }}
</div>
</template>
<script>
import { toRefs } from "vue";
export default {
props: {
count: {
type: Number,
default: 10,
}
},
setup(props) {
const { count } = toRefs(props);
return {
count,
};
},
};
</script>
06 onMounted
新的生命周期函数, 介于beforeCreate和created之间一个声明周期函数, 有两种调用方法
<template>
<div>
<ol>
<li v-for="(item,index) in list" :key="index">{{index+1}}. {{item.name}}</li>
</ol>
</div>
</template>
<script>
import { defineComponent, onMounted, ref } from "vue";
import axios from 'axios';
export default defineComponent({
name: "App",
setup() {
// 定义一个响应式的变量list
const list = ref([]);
// 获取数据
const getList = ()=> {
axios.get('http://huruqing.cn:3000/api/film/getList').then(res=> {
// 修改list,页面重新渲染
list.value = res.data.films;
})
}
// 在声明周期函数里自动调用getList去获取数据
onMounted(getList);
return {
list,
getList
};
},
});
</script>
07 watch函数
<template>
<div>
<h3>{{count}}</h3>
<button @click="count=100">修改count</button>
</div>
</template>
<script>
import { defineComponent, ref, watch} from "vue";
export default defineComponent({
name: "App",
setup() {
const count = ref(0);
watch(count,(n,o)=> {
console.log('新值',n);
console.log('旧值',o);
})
return {
count,
};
},
});
</script>
08 computed函数
(1)第一种情况: count2根据count计算得到
<template>
<div style="margin: 30px">
{{ count }}
</div>
<div style="margin: 30px">
{{ count2 }}
</div>
</template>
<script>
import { computed, ref, watch } from "vue";
export default {
setup(props) {
const count = ref(1);
const count2 = computed(() => count.value + 10);
return {
count,
count2,
};
},
};
</script>
(2) 第二种情况: count2根据count得到, 修改count2的同时也修改count的值
<template>
<div style="margin: 30px">
{{ count }}
</div>
<div style="margin: 30px">
{{ count2 }}
</div>
</template>
<script>
import { computed, ref, watch } from "vue";
export default {
setup(props) {
const count = ref(1);
const count2 = computed({
get: () => count.value + 1,
set: (val) => {
count.value = val - 1;
},
});
setTimeout(()=> {
count2.value = 10;
},2000)
return {
count,
count2,
};
},
};
</script>
09 父子组件通信
- 父传子, 通过属性
- 子传父, 通过emit
// 父组件
<template>
<div>
<!-- 使用Hello组件需要提供msg,Hello组件提供了send事件给父组件 -->
<Hello :msg="msg" @send="test"/>
</div>
</template>
<script>
import {defineComponent, ref} from "vue";
import Hello from './Hello.vue'
export default defineComponent({
name: "App",
components: {
Hello,
},
setup() {
const msg = ref('hello');
const test =(data)=> {
console.log(data);
}
return {
msg,
test
};
},
});
</script>
// 子组件
<template>
<div>
<h3>{{ msg }}</h3>
<!-- 通过emit发送数据给父组件 -->
<button @click="emit('send',22222222222)">发送信息</button>
</div>
</template>
<script>
import { defineComponent, toRefs } from "vue";
export default defineComponent({
props: {
msg: {
type: String,
},
},
/**
* @param props父组件传过来的属性
* @param context上下文对象
*/
setup(props, context) {
console.log("上下文对象", context);
const { msg } = toRefs(props);
// 把emit方法从context对象结构出来
const { emit } = context;
return {
msg,
emit
};
},
});
</script>
10 script标签的setup属性
<template>
<h1>{{ msg }}</h1>
</template>
<script setup>
const msg = 'Hello World!'
</script>
一些资源: Vue3+TypeScript 完整项目上手教程